﻿using UnityEngine;
using System.Collections;
using System.Collections.Generic;

public class Enemy : MonoBehaviour {

	// Keep track of the cell the AI is currently occupying
	public MazeCell currCell;
	// Keep track of which direction the AI is moving
	public MazeDirection direction;
	// Store which directions are available to the AI
	private MazeCellEdge[] passages;
	// Prevents the AI from only moving up.
	private float count = 0;
	// Delays the AI's decision process by a frame to prevent it from moving too early.
	private float timer = 1;
	// Allows the AI to move
	public bool canMove = true;
	// Allows the AI to backtrack
	public bool canBackTrack = false;
	// The color the AI paints cells.
	private readonly Color purpleSquare = new Color(.64f, .38f, .57f);
	
	// Update is called once per frame
	void Update () {
		// If the AI can move, run through this tree.
		if (canMove) {
			// Check what passages are available
			passages = currCell.passages ();
			// Also label the current cell with the AI's location
			currCell.hasEnemy = true;
			// If we're at a junction, then choose a direction.
			if (junctionCheck ()) {
				// Delay the decision by a second. If not done, the AI will move too early.
				timer -= Time.deltaTime;
				// If it's time to move, then change the direction, then reinitialize the timer.
				if (timer == 0) {
					changeDirection ();
					timer = 1;
				}
			}
			// If the count is high enough, then move.
			if (count == 10) {
				changeDirection ();
				count = 0;
			}
			// Get the current position and update it depending on which direction the AI is set to move
			Vector3 pos = transform.localPosition;
			if (direction.Equals (MazeDirection.North) && count < 10) {
				pos.y += .1f;
				count += 1;
			} else if (direction.Equals (MazeDirection.South) && count < 10) {
				pos.y -= .1f;
				count += 1;
			} else if (direction.Equals (MazeDirection.West) && count < 10) {
				pos.x -= .1f;
				count += 1;
			} else if (direction.Equals (MazeDirection.East) && count < 10) {
				pos.x += .1f;
				count += 1;
			}
			transform.localPosition = pos;
		}
	}

	// Is the current cell a junction?
	public bool junctionCheck() {
		// If there's only one passage to move to, not counting the one behind the AI, then it's not.
		if (passages.Length == 1) {
			return false;
			// Otherwise, check the other passages to make sure we're in a junction.
		} else {
			MazeDirection holder;
			for (int i = 0; i < passages.Length; i++) {
				holder = passages[i].direction;
				for(int j = i + 1; j < passages.Length; j++) {
					if (MazeDirections.isOpposite(holder, passages[j].direction)) {
						return true;
					}
				}
			}
			return false;
		}
	}

	// Adjusts the current direction if needed.
	void changeDirection() {
		// Determines the number of cells in each direction
		int[] arr = search (false);
		// Picks the greatest direction
		int max = Mathf.Max (arr);
		// Determines which direction to move.
		int index = 0;
		for (int i = 0; i < arr.Length; i++) {
			if (arr[i] == max) {
				index = i;
				break;
			}
		}
		// If we're allowed to backtrack, then move back until we find new cells to cover.
		if (canBackTrack) {
			MazeCellEdge[] passages = currCell.passages();
			bool allPurple = false;
			foreach(MazePassage passage in passages) {
				MazeCell newCell = currCell.getOtherCell(passage);
				SpriteRenderer rend = newCell.GetComponent<SpriteRenderer>();
				if(!rend.color.Equals (purpleSquare)){
					direction = passage.direction;
					canBackTrack = false;
					allPurple = false;
					break;
				}
				allPurple = true;
			}
			// If everything immediately surrounding the AI is purple, then just move back.
			if(allPurple) {
				direction = passages[index].direction;
			}
			// If we're in a dead end, then backtrack til we find a new path to cover.
		} else {
			if (deadCell (currCell)) {
				direction = MazeDirections.GetOpposite (direction);
				MazeCellEdge[] passages = currCell.passages ();
				MazeCell newCell = currCell.getOtherCell (passages [0]);
				SpriteRenderer rend = newCell.GetComponent<SpriteRenderer> ();
				if (!rend.color.Equals (Color.white)) {
					canBackTrack = true;
				}
				// Otherwise move down the best possible path.
			} else {
				MazeDirection newDirection = passages [index].direction;
				if (newDirection.Equals (MazeDirections.GetOpposite (direction))) {
					arr = search (true);
					max = Mathf.Max (arr);
					index = 0;
					for (int i = 0; i < arr.Length; i++) {
						if (arr [i] == max) {
							index = i;
							direction = passages [index].direction;
							break;
						}
					}
				} else {
					direction = newDirection;
				}
				//if the cell we're moving into is purple, then we should be able to backtrack. If it's not, then turn backtracking off.
				MazeCell nextCell = currCell.getOtherCell (passages [index]);
				SpriteRenderer rend = nextCell.GetComponent<SpriteRenderer> ();
				if (!rend.color.Equals (new Color (.64f, .38f, .57f))) {
					canBackTrack = false;
				}
				foreach (MazeCellEdge passage in currCell.passages ()) {
					nextCell = currCell.getOtherCell (passage);
					rend = nextCell.GetComponent<SpriteRenderer> ();
					if (!rend.color.Equals (new Color (.64f, .38f, .57f))) {
						canBackTrack = false;
						break;
					}
					canBackTrack = true;
				}
			}
		}
	}

	// Check each path and count how many cells are in that direction. checkBack makes sure we can't check bck if we don't need to.
	public int[] search(bool checkBack) {
		List<int> arr = new List<int>();
		if (!deadCell (currCell)) {
			foreach (MazeCellEdge passage in passages) {
				int i = totCell (currCell, currCell.getOtherCell (passage));
				arr.Add (i);
			}
		} else {
			arr.Add (totCell (null, currCell));
		}
		return arr.ToArray();
	}

	// Count the total number of cells the cell given by cell leads to. Pass in lastCell to make sure we're not counting that direction.
	public int totCell(MazeCell lastCell, MazeCell cell) {
		List<int> arr = new List<int>();
		int sum = 0;
		if (cell != null) {
			if (!deadCell (cell)) {
				foreach (MazeCellEdge passage in cell.passages()) {
					SpriteRenderer rend = cell.getOtherCell (passage).GetComponent<SpriteRenderer>();
					if(!cell.getOtherCell (passage).Equals(lastCell)) {
						if(rend.color.Equals (new Color(.64f, .38f, .57f)) && !canBackTrack) {
							arr.Add (0);
						}
						else if(rend.color.Equals (new Color(.64f, .38f, .57f)) && canBackTrack) {
							arr.Add (totCell (cell, cell.getOtherCell (passage)));
						}
						else {
							arr.Add (totCell (cell, cell.getOtherCell (passage)));
						}
					}
				}
				foreach (int num in arr.ToArray()) {
					sum += num;
				}
				return sum;
			} else {
				return 1;
			}
		} else {
			return 0;
		}
	}
	
	//Determines if a cell is a dead end
	public bool deadCell(MazeCell cell) {
		if (cell != null) {
			if (cell.passages ().Length <= 1) {
				return true;
			} else {
				return false;
			}
		} else
			return false;
	}

}
